package com.snack.db;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.sql.DataSource;

import org.apache.commons.dbutils.BasicRowProcessor;
import org.apache.commons.dbutils.CamelBeanProcessor;
import org.apache.commons.dbutils.DbUtils;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.RowProcessor;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;
import org.apache.commons.dbutils.handlers.StringArrayHandler;
import org.apache.commons.dbutils.handlers.StringArrayListHandler;
import org.apache.commons.dbutils.handlers.StringMapHandler;
import org.apache.commons.dbutils.handlers.StringMapListHandler;
import org.apache.log4j.Logger;

import com.mchange.v2.c3p0.ComboPooledDataSource;

/**
 * 数据库查询、执行处理帮助类。 需要 Apache Commons DbUtils 1.2。 Copyright: Copyright (c) Feb 6,
 * 2009 3:39:21 PM Company: 北京宽连十方数字技术有限公司 Author: chengyao Version: 1.1
 */
public class DbHelper {
	private static final Logger logger = Logger.getLogger(DbHelper.class);
	private static final Logger sqllogger = Logger
			.getLogger("com.cplatform.SQL");
	public static DataSource ds = new ComboPooledDataSource();
	public static final RowProcessor<Object> BEAN_ROW_PROCESSOR = new BasicRowProcessor(
			new CamelBeanProcessor());

	/**
	 * 获取数据源
	 * 
	 * @return 数据源对象
	 */
	public static DataSource getDataSource() {
		return ds;
	}

	/**
	 * 取得数据库连接
	 * 
	 * @return 数据库连接对象
	 */
	public static Connection getConn() {
		try {
			return ds.getConnection();
		} catch (SQLException e) {
			logger.error(e.getMessage(), e);
			return null;
		}
	}

	/**
	 * 释放数据库连接
	 * 
	 * @param conn
	 *            要释放的数据库连接
	 */
	public static void closeConn(Connection conn) {
		DbUtils.closeQuietly(conn);
	}

	/**
	 * 执行 SELECT 语句，返回单条查询结果为Map对象
	 * 
	 * @param sql
	 *            即将被执行的sql语句.
	 * @return 返回Map对象，出错则返回null
	 */
	public static Map<String, String> getItemMap(String sql) {
		return getItemMap(sql, (Object[]) null);
	}

	/**
	 * 带入指定的参数对象，执行 SELECT 语句，返回单条查询结果为Map对象
	 * 
	 * @param sql
	 *            即将被执行的sql语句.
	 * @param param
	 *            参数对象.
	 * @return 返回Map对象，出错则返回null
	 */
	public static Map<String, String> getItemMap(String sql, Object param) {
		return getItemMap(sql, new Object[] { param });
	}

	/**
	 * 带入指定的参数数组，执行 SELECT 语句，返回单条查询结果为Map对象
	 * 
	 * @param sql
	 *            即将被执行的sql语句.
	 * @param params
	 *            参数数组.
	 * @return 返回Map对象，出错则返回null
	 */
	public static Map<String, String> getItemMap(String sql, Object... params) {
		debug(sql, params);
		QueryRunner run = new QueryRunner(ds);
		try {
			return run.query(sql, new StringMapHandler(), params);
		} catch (SQLException ex) {
			logger.error(ex.getMessage(), ex);
			return null;
		}
	}

	/**
	 * 执行 SELECT 语句，返回单条查询结果为字符串数组
	 * 
	 * @param sql
	 *            即将被执行的sql语句.
	 * @return 返回字符串数组，出错则返回null
	 */
	public static String[] getItemArray(String sql) {
		return getItemArray(sql, (Object[]) null);
	}

	/**
	 * 带入指定的参数对象，执行 SELECT 语句，返回单条查询结果为字符串数组
	 * 
	 * @param sql
	 *            即将被执行的sql语句.
	 * @param param
	 *            参数对象.
	 * @return 返回字符串数组，出错则返回null
	 */
	public static String[] getItemArray(String sql, Object param) {
		return getItemArray(sql, new Object[] { param });
	}

	/**
	 * 带入指定的参数数组，执行 SELECT 语句，返回单条查询结果为字符串数组
	 * 
	 * @param sql
	 *            即将被执行的sql语句.
	 * @param params
	 *            参数数组.
	 * @return 返回字符串数组，出错则返回null
	 */
	public static String[] getItemArray(String sql, Object... params) {
		debug(sql, params);
		QueryRunner run = new QueryRunner(ds);
		try {
			return run.query(sql, new StringArrayHandler(), params);
		} catch (SQLException ex) {
			logger.error(ex.getMessage(), ex);
			return null;
		}
	}

	/**
	 * 带入指定的参数数组，执行 INSERT, UPDATE, 或者 DELETE 语句
	 * 
	 * @param sql
	 *            即将被执行的sql语句.
	 * @param params
	 *            参数数组.
	 * @return 影响的行数，-1表示出错
	 */
	public static int[] batch(String sql, List<Object[]> params) {
		debug(sql, new Object[] { "batch sql, count:"
				+ ((params == null) ? -1 : params.size()) });
		QueryRunner run = new QueryRunner(ds);
		try {
			Object[][] o = new Object[params.size()][];
			for (int i = 0; i < params.size(); i++) {
				o[i] = params.get(i);
			}
			return run.batch(sql, o);
		} catch (SQLException ex) {
			logger.error(ex.getMessage(), ex);
			return null;
		}
	}

	/**
	 * 执行 SELECT 语句，并把查询结果返回为Map列表
	 * 
	 * @param sql
	 *            即将被执行的sql语句.
	 * @return 返回Map的列表，出错则返回空列表
	 */
	public static List<Map<String, String>> getMapList(String sql) {
		return getMapList(sql, (Object[]) null);
	}

	/**
	 * 带入指定的参数对象，执行 SELECT 语句，并把查询结果返回为Map列表
	 * 
	 * @param sql
	 *            即将被执行的sql语句.
	 * @param param
	 *            参数对象.
	 * @return 返回Map的列表，出错则返回空列表
	 */
	public static List<Map<String, String>> getMapList(String sql, Object param) {
		return getMapList(sql, new Object[] { param });
	}

	/**
	 * 带入指定的参数数组，执行 SELECT 语句，并把查询结果返回为Map列表
	 * 
	 * @param sql
	 *            即将被执行的sql语句.
	 * @param params
	 *            参数数组.
	 * @return 返回Map的列表，出错则返回空列表
	 */
	public static List<Map<String, String>> getMapList(String sql,
			Object... params) {
		debug(sql, params);
		QueryRunner run = new QueryRunner(ds);
		try {
			return run.query(sql, new StringMapListHandler(), params);
		} catch (SQLException ex) {
			return new ArrayList<Map<String, String>>();
		}
	}

	/**
	 * 执行 SELECT 语句，并把查询结果返回为字符串数组列表
	 * 
	 * @param sql
	 *            即将被执行的sql语句.
	 * @return 返回字符串数组的列表，出错则返回空列表
	 */
	public static List<String[]> getArrayList(String sql) {
		return getArrayList(sql, (Object[]) null);
	}

	/**
	 * 带入指定的参数对象，执行 SELECT 语句，并把查询结果返回为字符串数组列表
	 * 
	 * @param sql
	 *            即将被执行的sql语句.
	 * @param param
	 *            参数对象.
	 * @return 返回字符串数组的列表，出错则返回空列表
	 */
	public static List<String[]> getArrayList(String sql, Object param) {
		return getArrayList(sql, new Object[] { param });
	}

	/**
	 * 带入指定的参数数组，执行 SELECT 语句，并把查询结果返回为字符串数组列表
	 * 
	 * @param sql
	 *            即将被执行的sql语句.
	 * @param params
	 *            参数数组.
	 * @return 返回字符串数组的列表，出错则返回空列表
	 */
	public static List<String[]> getArrayList(String sql, Object... params) {
		debug(sql, params);
		QueryRunner run = new QueryRunner(ds);
		try {
			return run.query(sql, new StringArrayListHandler(), params);
		} catch (SQLException ex) {
			ex.printStackTrace();
			return new ArrayList<String[]>();
		}
	}

	/**
	 * 执行 INSERT, UPDATE, 或者 DELETE 语句
	 * 
	 * @param sql
	 *            即将被执行的sql语句.
	 * @return 影响的行数，-1表示出错
	 */
	public static int execute(String sql) {
		return execute(sql, (Object[]) null);
	}

	/**
	 * 带入指定的参数对象，执行 INSERT, UPDATE, 或者 DELETE 语句
	 * 
	 * @param sql
	 *            即将被执行的sql语句.
	 * @param param
	 *            参数对象.
	 * @return 影响的行数，-1表示出错
	 */
	public static int execute(String sql, Object param) {
		return execute(sql, new Object[] { param });
	}

	/**
	 * 带入指定的参数数组，执行 INSERT, UPDATE, 或者 DELETE 语句
	 * 
	 * @param sql
	 *            即将被执行的sql语句.
	 * @param params
	 *            参数数组.
	 * @return 影响的行数，-1表示出错
	 */
	public static int execute(String sql, Object... params) {
		debug(sql, params);
		QueryRunner run = new QueryRunner(ds);
		try {
			return run.update(sql, params);
		} catch (SQLException ex) {
			logger.error(ex.getMessage(), ex);
			return -1;
		}
	}

	/**
	 * 给定SQL和指定的类，就可以返回一个对象（如果结果集有多行，则只返回首行）。
	 * 
	 * @param sql
	 *            即将被执行的sql语句.
	 * @param type
	 *            指定类
	 * @return 获取的对象.(如果结果集为空，则返回null)
	 */
	public static <T> T getBean(String sql, Class<T> type) {
		return getBean(sql, type, (Object[]) null);
	}

	/**
	 * 给定SQL和指定的类，就可以返回一个对象（如果结果集有多行，则只返回首行）。
	 * 
	 * @param sql
	 *            即将被执行的sql语句.
	 * @param type
	 *            指定类
	 * @param param
	 *            参数
	 * @return 获取的对象.(如果结果集为空，则返回null)
	 */
	public static <T> T getBean(String sql, Class<T> type, Object param) {
		return getBean(sql, type, new Object[] { param });
	}

	/**
	 * 给定SQL和指定的类，就可以返回一个对象（如果结果集有多行，则只返回首行）。
	 * 
	 * @param sql
	 *            即将被执行的sql语句.
	 * @param type
	 *            指定类
	 * @param params
	 *            参数数组
	 * @return 获取的对象.(如果结果集为空，则返回null)
	 */
	public static <T> T getBean(String sql, Class<T> type, Object... params) {
		QueryRunner run = new QueryRunner(ds);
		try {
			return run.query(sql, new BeanHandler<T>(type, BEAN_ROW_PROCESSOR),
					params);
		} catch (SQLException ex) {
			logger.error(ex.getMessage(), ex);
			return null;
		}
	}

	/**
	 * 给定SQL和指定的类，就可以返回一个对象列表
	 * 
	 * @param sql
	 *            即将被执行的sql语句.
	 * @param type
	 *            指定类
	 * @param params
	 *            参数数组
	 * @return 获取的对象列表.(如果结果集为空，则返回null)
	 */
	public static <T> List<T> getBeanList(String sql, Class<T> type,
			Object... params) {
		QueryRunner run = new QueryRunner(ds);
		try {
			return run.query(sql, new BeanListHandler<T>(type,
					BEAN_ROW_PROCESSOR), params);
		} catch (SQLException ex) {
			logger.error(ex.getMessage(), ex);
			return null;
		}
	}

	/**
	 * 给定SQL和指定的类，就可以返回一个对象列表
	 * 
	 * @param sql
	 *            即将被执行的sql语句.
	 * @param type
	 *            指定类
	 * @return 获取的对象列表.(如果结果集为空，则返回长度为0的list)
	 */
	public static <T> List<T> getBeanList(String sql, Class<T> type) {
		return getBeanList(sql, type, (Object[]) null);
	}

	/**
	 * 给定SQL和指定的类，就可以返回一个对象列表
	 * 
	 * @param sql
	 *            即将被执行的sql语句.
	 * @param type
	 *            指定类
	 * @param param
	 *            查询参数
	 * @return 获取的对象列表.(如果结果集为空，则返回长度为0的list)
	 */
	public static <T> List<T> getBeanList(String sql, Class<T> type,
			Object param) {
		return getBeanList(sql, type, new Object[] { param });
	}

	/**
	 * 根据SQL查询出结果集中的第一个字段的值
	 * 
	 * @param sql
	 *            执行的SQL语句
	 * @return 查询结果
	 */
	public static String queryScalar(String sql) {
		return queryScalar(sql, (Object[]) null);
	}

	/**
	 * 根据SQL查询出结果集中的第一个字段的值
	 * 
	 * @param sql
	 *            执行的SQL语句
	 * @param param
	 *            参数
	 * @return 查询结果
	 */
	public static String queryScalar(String sql, Object param) {
		return queryScalar(sql, new Object[] { param });
	}

	/**
	 * 根据SQL查询出结果集中的第一个字段的值
	 * 
	 * @param sql
	 *            执行的SQL语句
	 * @param params
	 *            参数数组
	 * @return 查询结果
	 */
	public static String queryScalar(String sql, Object... params) {
		QueryRunner run = new QueryRunner(ds);
		try {
			Object obj = run.query(sql, new ScalarHandler(1), params);
			if (obj != null) {
				return obj.toString();
			}
		} catch (SQLException ex) {
			logger.error(ex.getMessage(), ex);
			return null;
		} catch (Exception ex) {
			logger.error(ex.getMessage(), ex);
			return null;
		}
		return null;
	}

	/**
	 * 输出debug信息
	 * 
	 * @param sql
	 *            执行的SQL语句
	 * @param params
	 *            执行的参数
	 */
	private static void debug(String sql, Object... params) {
		if (sqllogger.isDebugEnabled()) {
			if (params == null) {
				params = new Object[] {};
			}
			StringBuilder sb = new StringBuilder(400);
			sb.append(sql);
			if (params.length != 0) {
				sb.append(" [params:");
				for (Object obj : params) {
					sb.append(obj == null ? "<null>" : obj.toString()).append(
							", ");
				}
				sb.setLength(sb.length() - 2);
				sb.append("]");
			}
			sqllogger.debug(sb.toString());
		}
	}
}